﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MainPresenter.cs" company="SMART business">
//   Copyright (c) 2014 All Rights Reserved
// </copyright>
// <summary>
//   The main presenter.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ComparisonTool.Presenters
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Threading;

    using ComparisonTool.Connection;
    using ComparisonTool.Forms;
    using ComparisonTool.Forms.Interfaces;
    using ComparisonTool.Interfaces;
    using ComparisonTool.Models;

    /// <summary>
    /// The main presenter.
    /// </summary>
    public class MainPresenter
    {
        private delegate void DelegateMethod();

        /// <summary>
        /// The wait dialog.
        /// </summary>
        private readonly Wait wait;

        /// <summary>
        /// The connection manager.
        /// </summary>
        private readonly ConnectionManager connectionManager;

        /// <summary>
        /// The inverse.
        /// </summary>
        private bool inverse = true;

        /// <summary>
        /// The lock object.
        /// </summary>
        private readonly object lockObject = new object();

        /// <summary>
        /// The _view.
        /// </summary>
        private readonly IMainForm view;

        /// <summary>
        /// The extended interface.
        /// </summary>
        private readonly IXrm xrm;

        /// <summary>
        /// The _message service.
        /// </summary>
        private readonly IMessageService messageService;

        /// <summary>
        /// The _compared results.
        /// </summary>
        private readonly IComparedResults comparedResults;

        /// <summary>
        /// The _current entities.
        /// </summary>
        private string currentEntity;

        /// <summary>
        /// The comparing type.
        /// </summary>
        private int compareType;

        private bool isEntitiesLoaded;

        public MainPresenter(IMainForm mainForm, IXrm xrm, IMessageService messageService, IComparedResults comparedResults)
        {
            this.view = mainForm;
            this.xrm = xrm;
            this.messageService = messageService;
            this.comparedResults = comparedResults;
            this.wait = new Wait();

            this.view.LoadEntities += this.LoadEntitiesClick;
            this.view.LoadDoubleEntities += this.LoadDoubleEntities;

            this.view.EntitySelect += this.EntitySelect;

            this.view.CompareAttributes += this.Compare;

            this.view.FormSelected += this.FormSelected;
            this.view.ExportToExcel += this.ExportToExcel;

            this.connectionManager = new ConnectionManager(this.view);

            this.connectionManager.ConnectionSucceed += this.СonnectionSucceed;
            this.connectionManager.ConnectionFailed += this.ConnectionFailed;

            this.view.ShowSameEntities += this.ShowSameEntities;
            this.view.ShowDistinctEntity += this.ShowDistinctEntity;

            this.view.EntitiesCompare += this.EntitiesCompare;

            this.view.InverseCompare += this.InverseCompare;
        }

        /// <summary>
        /// The inverse compare.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void InverseCompare(object sender, EventArgs e)
        {
            this.inverse = !this.inverse;
        }

        /// <summary>
        /// The entities compare.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void EntitiesCompare(object sender, EventArgs e)
        {
            if (!this.xrm.IsConnected())
            {
                this.messageService.ShowExclamation("No connection.");
                return;
            }

            this.view.SetEntityCaption(1, this.GetOrgInfo(1, false));
            this.view.SetEntityCaption(2, this.GetOrgInfo(2, false));
        }

        /// <summary>
        /// The view forms.
        /// </summary>
        private enum ViewForms
        {
            /// <summary>
            /// The form 1.
            /// </summary>
            Form1 = 1,

            /// <summary>
            /// The form 2.
            /// </summary>
            Form2 = 2
        }

        /// <summary>
        /// Gets or sets the organization friendly name 1.
        /// </summary>
        private string OrganizationFriendlyName1 { get; set; }

        /// <summary>
        /// Gets or sets the organization friendly name 2.
        /// </summary>
        private string OrganizationFriendlyName2 { get; set; }

        /// <summary>
        /// Gets or sets the current entities.
        /// </summary>
        private string CurrentEntity
        {
            get
            {
                return this.currentEntity;
            }

            set
            {
                if (string.IsNullOrEmpty(value))
                {
                    this.view.SetCurrentEntityValue();
                }

                this.currentEntity = value;

                this.view.SetOrg1Caption(this.xrm.GetOrgInfo(1));
                this.view.SetOrg2Caption(this.xrm.GetOrgInfo(2));
            }
        }

        /// <summary>
        /// The connection succeed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void СonnectionSucceed(object sender, ConnectionSucceedEventArgs e)
        {
            this.connectionManager.RebuildConnectionList();

            switch (e.Id)
            {
                case 1:
                    this.OrganizationFriendlyName1 = e.ConnectionDetail.OrganizationFriendlyName;

                    new Thread(() => this.view.SetOrg1Caption(this.OrganizationFriendlyName1)).Start();

                    break;
                case 2:
                    this.OrganizationFriendlyName2 = e.ConnectionDetail.OrganizationFriendlyName;

                    new Thread(() => this.view.SetOrg2Caption(this.OrganizationFriendlyName2)).Start();

                    break;
            }

            this.xrm.СonnectionSucceed(e.OrganizationService, e.ConnectionDetail, e.Id);
            this.connectionManager.SetConnectionStatus(true, e.ConnectionDetail, e.Id);
        }

        /// <summary>
        /// The connection failed.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            this.messageService.ShowError(e.FailureReason);
            this.view.SetStatusConnection("Not connected.", e.Id);
            this.xrm.СonnectionSucceed(null, null, e.Id);
        }

        /// <summary>
        /// The _view_ export to excel.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ExportToExcel(object sender, EventArgs e)
        {
            if (!this.comparedResults.UploadResults(this.xrm))
            {
                this.messageService.ShowError("Error uploading!");
            }

            this.messageService.ShowMessage("File successfully saved.");
        }

        /// <summary>
        /// The form selected.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void FormSelected(object sender, EventArgs e)
        {
            this.view.SetOrg1Caption(this.GetOrgInfo(1));
            this.view.SetOrg2Caption(this.GetOrgInfo(2));
        }

        #region Load Entities

        /// <summary>
        /// The load entities click.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void LoadEntitiesClick(object sender, EventArgs e)
        {
            try
            {
                if (!this.xrm.IsConnected())
                {
                    this.messageService.ShowExclamation("No connection.");
                    return;
                }

                this.isEntitiesLoaded = false;

                new Thread(() =>
                {
                    this.xrm.RetrieveEntities(1);
                    this.LoadEntitiesCompleted();
                }).Start();

                new Thread(() =>
                {
                    this.xrm.RetrieveEntities(2);
                    this.LoadEntitiesCompleted();
                }).Start();

                this.wait.Show(this.view.GetMainForm());
            }
            catch (Exception ex)
            {
                this.messageService.ShowError(ex.Message);
            }
        }

        /// <summary>
        /// The load double entities completed.
        /// </summary>
        private void LoadDoubleEntitiesCompleted()
        {
            lock (this.lockObject)
            {
                if (!this.isEntitiesLoaded)
                {
                    this.isEntitiesLoaded = true;
                    return;
                }

                try
                {
                    var entities1 = this.xrm.GetEntities(1);

                    if (entities1 != null)
                    {
                        var result = (from dynamic entity in entities1
                                      where entity.DisplayName.UserLocalizedLabel != null
                                      select
                                          new
                                              {
                                                  DisplayName = entity.DisplayName.UserLocalizedLabel.Label,
                                                  LogicalName = entity.LogicalName.ToString(),
                                                  IsAuditEnabled = entity.IsAuditEnabled.Value.ToString(),
                                                  IsDuplicateDetectionEnabled = entity.IsDuplicateDetectionEnabled.Value.ToString()
                                              }).Cast<object>().ToList();

                        this.view.SetEntitiesList(1, result);
                        this.view.SetEntityCaption(1, this.GetOrgInfo(1, false) + " : " + result.Count);
                    }

                    var entities2 = this.xrm.GetEntities(2);

                    if (entities2 != null)
                    {
                        var result = (from dynamic entity in entities2
                                      where entity.DisplayName.UserLocalizedLabel != null
                                      select
                                          new
                                          {
                                              DisplayName = entity.DisplayName.UserLocalizedLabel.Label,
                                              LogicalName = entity.LogicalName.ToString(),
                                              IsAuditEnabled = entity.IsAuditEnabled.Value.ToString(),
                                              IsDuplicateDetectionEnabled = entity.IsDuplicateDetectionEnabled.Value.ToString()
                                          }).Cast<object>().ToList();

                        this.view.SetEntitiesList(2, result);
                        this.view.SetEntityCaption(2, this.GetOrgInfo(2, false) + " : " + result.Count);
                    }

                    this.CloseWaitForm();
                }
                catch (Exception)
                {
                    this.messageService.ShowError("Loading entities error.");
                }
            }
        }

        /// <summary>
        /// The load entities completed.
        /// </summary>
        private void LoadEntitiesCompleted()
        {
            lock (this.lockObject)
            {
                if (!this.isEntitiesLoaded)
                {
                    this.isEntitiesLoaded = true;
                    return;
                }

                try
                {
                    var entities1 = this.xrm.GetEntities(1).ToList<dynamic>();
                    var entities2 = this.xrm.GetEntities(2).ToList<dynamic>();

                    var entityMetadata1 = entities1.Where(p => p.DisplayName.UserLocalizedLabel != null).ToArray();
                    var entityMetadata2 = entities2.Where(p => p.DisplayName.UserLocalizedLabel != null).ToArray();

                    var result = from entity1 in entityMetadata1
                                 from entity2 in entityMetadata2
                                 where entity1.LogicalName == entity2.LogicalName && !string.IsNullOrEmpty(entity1.DisplayName.UserLocalizedLabel.Label)
                                 select new
                                 {
                                     LogicalName = entity1.LogicalName.ToString(),
                                     DisplayName = entity1.DisplayName.UserLocalizedLabel.Label
                                 };

                    var entities = new List<object>();

                    foreach (var entity in result)
                    {
                        entities.Add(new
                                         {
                                             LogicalName = entity.LogicalName.ToString(),
                                             DisplayName = entity.DisplayName.ToString()
                                         });
                    }

                    this.CloseWaitForm();
                    this.view.SetEntitiesList(entities);
                    this.view.SetEntitiesCount(string.Format("Total entities count: {0}", entities.Count));
                }
                catch (Exception)
                {
                    this.messageService.ShowError("Loading entities error.");
                }
            }
        }

        private void CloseWaitForm()
        {
            if (this.wait.InvokeRequired)
            {
                var callback = new DelegateMethod(this.CloseWaitForm);
                this.wait.Invoke(callback);
            }
            else
            {
                this.wait.Hide();
            }
        }

        #endregion Load Entities

        #region Entity Selecting

        /// <summary>
        /// The entities select.
        /// </summary>
        /// <param name="entityName">
        /// The entities name.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void EntitySelect(object entityName, EventArgs e)
        {
            try
            {
                this.CurrentEntity = (string)entityName;

                new Thread(() => this.SystemFormLoadCompleted(this.xrm.RetrieveEntityForms(1, this.CurrentEntity), ViewForms.Form1)).Start();

                new Thread(() => this.SystemFormLoadCompleted(this.xrm.RetrieveEntityForms(2, this.CurrentEntity), ViewForms.Form2)).Start();

                this.wait.Opened = true;
                this.wait.Show(this.view.GetMainForm());
            }
            catch (Exception)
            {
                this.messageService.ShowError("Error loading forms.");
            }
        }

        /// <summary>
        /// The system form load completed.
        /// </summary>
        /// <param name="entityForms">
        /// The entities forms.
        /// </param>
        /// <param name="form">
        /// The form.
        /// </param>
        private void SystemFormLoadCompleted(List<object> entityForms, ViewForms form)
        {
            lock (this.lockObject)
            {
                try
                {
                    if (form == ViewForms.Form1)
                    {
                        this.view.SetForms1List(entityForms);
                        this.view.SetEntityCaption(1, this.GetOrgInfo(1, false));
                    }
                    else
                    {
                        this.view.SetForms2List(entityForms);
                        this.view.SetEntityCaption(2, this.GetOrgInfo(2, false));
                    }

                    if (this.wait.Opened && this.wait.IsHandleCreated)
                    {
                        this.CloseWaitForm();
                    }
                }
                catch (Exception)
                {
                    this.messageService.ShowError("Loading forms error.");
                }
            }
        }

        #endregion Entity Selecting

        #region Comparing

        /// <summary>
        /// The show distinct entities.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ShowDistinctEntity(object sender, EventArgs e)
        {
            try
            {
                if (!this.xrm.IsConnected())
                {
                    throw new Exception("No connection.");
                }

                var entities1 = this.xrm.GetEntities(1);
                var entities2 = this.xrm.GetEntities(2);

                if (entities1 == null || entities2 == null)
                {
                    throw new Exception("Entities are absent.");
                }

                var entitiesCollection1 = (from dynamic entity in entities1
                                           where entity.DisplayName.UserLocalizedLabel != null
                                           select
                                               new DiffEntity
                                                   {
                                                       LogicalName = entity.LogicalName,
                                                       DisplayName =
                                                           entity.DisplayName.UserLocalizedLabel.Label,
                                                       IsAuditEnabled =
                                                           entity.IsAuditEnabled.Value.ToString(),
                                                       IsDuplicateDetectionEnabled =
                                                           entity.IsDuplicateDetectionEnabled.Value
                                                           .ToString()
                                                   }).ToList<object>();

                var entitiesCollection2 = (from dynamic entity in entities2
                                           where entity.DisplayName.UserLocalizedLabel != null
                                           select
                                               new DiffEntity
                                                   {
                                                       LogicalName = entity.LogicalName,
                                                       DisplayName =
                                                           entity.DisplayName.UserLocalizedLabel.Label,
                                                       IsAuditEnabled =
                                                           entity.IsAuditEnabled.Value.ToString(),
                                                       IsDuplicateDetectionEnabled =
                                                           entity.IsDuplicateDetectionEnabled.Value
                                                           .ToString()
                                                   }).ToList<object>();

                var entitiesDiff1 = entitiesCollection1.Except(entitiesCollection2);
                var entitiesDiff2 = entitiesCollection2.Except(entitiesCollection1);

                var entities = new List<object>();

                foreach (dynamic entity in entitiesDiff1)
                {
                    entities.Add(
                        new
                            {
                                LogicalName = entity.LogicalName.ToString(),
                                DisplayName = entity.DisplayName.ToString(),
                                IsAuditEnabled = entity.IsAuditEnabled.ToString(),
                                IsDuplicateDetectionEnabled = entity.IsDuplicateDetectionEnabled.ToString()
                            });
                }

                this.view.SetEntitiesList(1, entities);
                this.view.SetEntityCaption(1, this.GetOrgInfo(1, false) + " : " + entities.Count);

                entities = new List<object>();

                foreach (dynamic entity in entitiesDiff2)
                {
                    entities.Add(
                        new
                            {
                                LogicalName = entity.LogicalName.ToString(),
                                DisplayName = entity.DisplayName.ToString(),
                                IsAuditEnabled = entity.IsAuditEnabled.ToString(),
                                IsDuplicateDetectionEnabled = entity.IsDuplicateDetectionEnabled.ToString()
                            });
                }

                this.view.SetEntitiesList(2, entities);
                this.view.SetEntityCaption(2, this.GetOrgInfo(2, false) + " : " + entities.Count);
            }
            catch (Exception ex)
            {
                this.messageService.ShowError(ex.Message);
            }
        }

        /// <summary>
        /// The show same entities.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void ShowSameEntities(object sender, EventArgs e)
        {
            try
            {
                if (!this.xrm.IsConnected())
                {
                    throw new Exception("No connection.");
                }

                var entities1 = this.xrm.GetEntities(1);
                var entities2 = this.xrm.GetEntities(2);

                if (entities1 == null || entities2 == null)
                {
                    throw new Exception("Entities are absent.");
                }

                var result = (from dynamic entity1 in entities1
                              from dynamic entity2 in entities2
                              where
                                  entity1.DisplayName.UserLocalizedLabel != null
                                  && entity2.DisplayName.UserLocalizedLabel != null
                                  && entity1.LogicalName == entity2.LogicalName
                              select
                                  new
                                      {
                                          LogicalName = entity1.LogicalName.ToString(),
                                          DisplayName = entity1.DisplayName.UserLocalizedLabel.Label,
                                          IsAuditEnabled = entity1.IsAuditEnabled.Value.ToString(),
                                          IsDuplicateDetectionEnabled =
                                  entity1.IsDuplicateDetectionEnabled.Value.ToString()
                                      }).ToList<object>();

                this.view.SetEntitiesList(1, result);
                this.view.SetEntityCaption(1, this.GetOrgInfo(1, false) + " : " + result.Count);

                result = (from dynamic entity1 in entities1
                          from dynamic entity2 in entities2
                          where
                              entity1.DisplayName.UserLocalizedLabel != null
                              && entity2.DisplayName.UserLocalizedLabel != null
                              && entity1.LogicalName == entity2.LogicalName
                          select
                              new
                                  {
                                      LogicalName = entity2.LogicalName.ToString(),
                                      DisplayName = entity2.DisplayName.UserLocalizedLabel.Label,
                                      IsAuditEnabled = entity2.IsAuditEnabled.Value.ToString(),
                                      IsDuplicateDetectionEnabled = entity2.IsDuplicateDetectionEnabled.Value.ToString()
                                  })
                    .ToList<object>();

                this.view.SetEntitiesList(2, result);
                this.view.SetEntityCaption(2, this.GetOrgInfo(2, false) + " : " + result.Count);
            }
            catch (Exception ex)
            {
                this.messageService.ShowError(ex.Message);
            }
        }

        /// <summary>
        /// The load double entities.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void LoadDoubleEntities(object sender, EventArgs e)
        {
            try
            {
                if (!this.xrm.IsConnected())
                {
                    this.messageService.ShowExclamation("No connection.");
                    return;
                }

                this.isEntitiesLoaded = false;

                new Thread(() =>
                {
                    this.xrm.RetrieveEntities(1);
                    this.LoadDoubleEntitiesCompleted();
                }).Start();

                new Thread(() =>
                {
                    this.xrm.RetrieveEntities(2);
                    this.LoadDoubleEntitiesCompleted();
                }).Start();

                this.wait.Show(this.view.GetMainForm());
            }
            catch (Exception ex)
            {
                this.messageService.ShowError(ex.Message);
            }
        }

        /// <summary>
        /// The compare.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void Compare(object sender, EventArgs e)
        {
            try
            {
                if (!this.xrm.IsConnected())
                {
                    this.messageService.ShowExclamation("No connection.");
                    return;
                }

                if (this.view.GetSelectedEntityCount().Equals(0))
                {
                    this.messageService.ShowExclamation("No entities selected.");
                    return;
                }

                var form1 = this.view.GetForm1();
                var form2 = this.view.GetForm2();

                if (form1 == null || form2 == null || string.IsNullOrEmpty(form1.Name)
                    || string.IsNullOrEmpty(form2.Name))
                {
                    this.messageService.ShowExclamation("You must select both entities forms before comparing!");
                    return;
                }

                var form1Xml = this.xrm.GetFormXml(1, form1.Name, form1.Value);
                var form2Xml = this.xrm.GetFormXml(2, form2.Name, form2.Value);

                var controlType = (CompareType)sender;

                string[] items1 = null;
                string[] items2 = null;

                JsEvent[] events1 = null;
                JsEvent[] events2 = null;

                BusinessRule[] rules1 = null;
                BusinessRule[] rules2 = null;

                switch (controlType)
                {
                    case CompareType.Attributes:
                        this.compareType = (int)CompareType.Attributes;
                        this.xrm.CompareAttributes(form1Xml, form2Xml, out items1, out items2);
                        break;

                    case CompareType.Tabs:
                        this.compareType = (int)CompareType.Tabs;
                        this.xrm.CompareTabs(form1Xml, form2Xml, out items1, out items2);
                        break;

                    case CompareType.Sections:
                        this.compareType = (int)CompareType.Sections;
                        this.xrm.CompareSections(form1Xml, form2Xml, out items1, out items2);
                        break;

                    case CompareType.Relationships:
                        this.compareType = (int)CompareType.Relationships;
                        this.xrm.CompareNavigationItems(form1Xml, form2Xml, out items1, out items2);
                        break;

                    case CompareType.Events:
                        this.compareType = (int)CompareType.Events;
                        this.xrm.CompareEvents(form1Xml, form2Xml, out events1, out events2);
                        break;
                    case CompareType.BusinessRules:
                        if (this.xrm.GetBuildNumber1() == 5 || this.xrm.GetBuildNumber2() == 5)
                        {
                            throw new Exception("One of CRM Organizations is CRM 2011. Compare rules is not feasible.");
                        }

                        this.compareType = (int)CompareType.BusinessRules;
                        this.xrm.CompareRules(this.CurrentEntity, out rules1, out rules2);
                        break;
                }

                if (controlType.Equals(CompareType.Events))
                {
                    if (events1 != null)
                    {
                        IEnumerable<JsEvent> firstEntity;
                        IEnumerable<JsEvent> secondEntity;

                        if (this.inverse)
                        {
                            firstEntity = events1.Except(events2);
                            secondEntity = events2.Except(events1);
                        }
                        else
                        {
                            firstEntity = events1.Intersect(events2);
                            secondEntity = events2.Intersect(events1);
                        }

                        this.comparedResults.Events1 = this.GetEventsList(firstEntity);
                        this.comparedResults.Events2 = this.GetEventsList(secondEntity);

                        this.view.SetEventsList(1, this.comparedResults.Events1);
                        this.view.SetEventsList(2, this.comparedResults.Events2);

                        if (this.comparedResults.Events1.Count().Equals(0) && this.comparedResults.Events2.Count().Equals(0))
                        {
                            this.messageService.ShowExclamation("All events are the same.");
                        }
                    }
                }
                else if (controlType.Equals(CompareType.BusinessRules))
                {
                    if (rules1 != null)
                    {
                        var firstEntity = this.inverse ? rules1.Except(rules2) : rules1.Intersect(rules2);
                        var secondEntity = this.inverse ? rules2.Except(rules1) : rules2.Intersect(rules1);

                        this.comparedResults.Rules1 = this.GetRulesList(firstEntity);
                        this.comparedResults.Rules2 = this.GetRulesList(secondEntity);

                        this.view.SetRulesList(1, this.comparedResults.Rules1);
                        this.view.SetRulesList(2, this.comparedResults.Rules2);

                        if (this.comparedResults.Rules1.Count().Equals(0) && this.comparedResults.Rules2.Count().Equals(0))
                        {
                            this.messageService.ShowExclamation("All rules are the same.");
                        }
                    }
                }
                else
                {
                    if (items1 != null)
                    {
                        var firstEntity = this.inverse ? items1.Except(items2).ToList() : items1.Intersect(items2).ToList();
                        var secondEntity = this.inverse ? items2.Except(items1).ToList() : items2.Intersect(items1).ToList();

                        this.comparedResults.Attributes1 = new Item(this.compareType, this.GetItemsList(firstEntity, form1Xml, controlType));
                        this.comparedResults.Attributes2 = new Item(this.compareType, this.GetItemsList(secondEntity, form2Xml, controlType));

                        var values1 = this.comparedResults.GetAttributes(1, this.compareType);
                        var values2 = this.comparedResults.GetAttributes(2, this.compareType);

                        this.view.SetAttributesList(1, values1);
                        this.view.SetAttributesList(2, values2);

                        if (values1.Count().Equals(0) && values2.Count().Equals(0))
                        {
                            this.messageService.ShowExclamation("All objects are the same.");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.messageService.ShowError("Error compare attributes: " + ex);
            }
        }

        /// <summary>
        /// The get rules list.
        /// </summary>
        /// <param name="rules">
        /// The rules.
        /// </param>
        /// <returns>
        /// The <see cref="System.Windows.Forms.ListViewItem"/>.
        /// </returns>
        private List<object> GetRulesList(IEnumerable<object> rules)
        {
            var list = new List<object>();

            foreach (dynamic rule in rules)
            {
                list.Add(new
                             {
                                 CreatedBy = rule.CreatedBy,
                                 RuleName = rule.RuleName.ToString(),
                                 State = rule.State.ToString(),
                                 IsManaged = rule.IsManaged.ToString()
                             });
            }

            return list;
        }

        /// <summary>
        /// The get events list.
        /// </summary>
        /// <param name="events">
        /// The events.
        /// </param>
        /// <returns>
        /// The <see cref="System.Windows.Forms.ListViewItem"/>.
        /// </returns>
        private List<object> GetEventsList(IEnumerable<JsEvent> events)
        {
            var list = new List<object>();
            foreach (var item in events)
            {
                list.Add(new
                             {
                                 Name = item.Name.ToString(CultureInfo.InvariantCulture),
                                 AttributeDisplayName = item.AttributeDisplayName.ToString(CultureInfo.InvariantCulture),
                                 Attribute = item.Attribute.ToString(CultureInfo.InvariantCulture),
                                 LibraryName = item.LibraryName.ToString(CultureInfo.InvariantCulture),
                                 FunctionName = item.FunctionName.ToString(CultureInfo.InvariantCulture)
                             });
            }

            return list;
        }

        private List<object> GetItemsList(IEnumerable<string> entities, string formXml, CompareType controlType)
        {
            var list = new List<object>();
            foreach (var entity in entities)
            {
                list.Add(new
                             {
                                 DisplayName = this.xrm.GetDisplayName(formXml, entity, controlType),
                                 Name = entity,
                                 TypeName = this.xrm.GetAttributeType(formXml, entity, controlType),
                                 IsReadOnly = this.xrm.IsReadOnly(formXml, entity),
                                 IsHidden = this.xrm.IsHidden(formXml, entity)
                             });
            }

            return list;
        }

        #endregion Comparing

        /// <summary>
        /// The get org info.
        /// </summary>
        /// <param name="id">
        /// The orgId.
        /// </param>
        /// <param name="fullInfo">
        /// The full info.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private string GetOrgInfo(int id, bool fullInfo = true)
        {
            var url = string.Empty;

            switch (id)
            {
                case 1:
                    url = this.OrganizationFriendlyName1;
                    break;

                case 2:
                    url = this.OrganizationFriendlyName2;
                    break;
            }

            if (!fullInfo)
            {
                return url;
            }

            string entity;
            string selectedForm;
            {
                string entityDisplayName = null;

                if (this.xrm.IsConnected())
                {
                    entityDisplayName = this.xrm.GetEntityValueByName(id, this.CurrentEntity);
                }

                entity = string.IsNullOrEmpty(entityDisplayName) ? string.Empty : " -> " + entityDisplayName;

                var form1Name = this.view.GetForm1().Name;
                var form2Name = this.view.GetForm2().Name;

                selectedForm = id.Equals(1)
                                ? (string.IsNullOrEmpty(form1Name) ? string.Empty : " -> " + form1Name + " form")
                                : (string.IsNullOrEmpty(form2Name) ? string.Empty : " -> " + form2Name + " form");
            }

            return url + entity + selectedForm;
        }
    }
}
